<?php
/**
 * Created by sublime 3.
 * Auth: Inhere
 * Date: 15-1-20
 * Time: 10:35
 * Uesd: 主要功能是 hi
 * AbstractWebApplication.php
 */

namespace ulue\core\application;

use Debug, Ioc, Ulue;
use ulue\core\module\AbstractModule;
use ulue\core\response\Response;
use ulue\core\request\InterfaceRequest;
use ulue\core\response\InterfaceResponse;

abstract class AbstractWebApplication extends AbstractApplication
{

    /**
     * The application response object.
     * @var    object
     */
    private $response;

    /**
     * 是否启用 压缩输出数据
     * @var boolean
     */
    public $enabledCompress = false;

    /**
     * @event Event an event raised before the application starts to handle a request.
     */
    const EVENT_BEFORE_EXECUTE = 'beforeExecute';

    /**
     * @event Event an event raised after the application successfully handles a request (before the response is sent out).
     */
    const EVENT_AFTER_EXECUTE = 'afterExecute';


    public function execute()
    {
        $this->beforeExecute();

        // @event onBeforeExecute

        $this->beginExecute();

        // @event onAfterExecute

        $this->afterExecute();

        // @event onBeforeRespond

        // Send the application response.
        $this->respond();

        // @event onAfterRespond
    }

    public function respond($returnBody = false)
    {
        // If gzip compression is enabled in configuration and the server is compliant, compress the output.
        if ($this->enabledCompress && !ini_get('zlib.output_compression') && (ini_get('output_handler') != 'ob_gzhandler'))
        {
            // $this->response->compress(\Ioc::$box->client->getEncodings());
            $this->response->compress('gzip');
        }

        return $this->response->send($returnBody);
    }


    /**
     * Instantiate the application module  activeModule
     * 激活要访问的模块
     * @param string|array $mRoute
     * @throws TheAppException
     * @throws \DRequestException
     * @throws \DRuntimeException
     * @return Module
     */
    public function activeModule($mRoute)
    {
        $mRoute = $mRoute ? : $this->defaultModule;

        if ( !$mRoute ) {
            throw new \DInvalidArgumentException("没有模块访问路由信息，无法匹配解析资源！");
        }

        Debug::trace("i 准备激活并进入应用模块",[ 'module Route' => $mRoute ]);

        $temp = $mRoute;

        if ( strpos($mRoute, '/') ) {
            list($name, $mRoute)  = explode('/', $mRoute, 2);
        } else {
            $name  = $mRoute;
            $route = $mRoute = '';
        }

        // 查找顶级模块; 若不存在则访问 默认模块 {@link $defautlModule}
        if ( ! isset($this->modules[$name]) ) {
            $name = $this->defaultModule;
            $route = $mRoute = $temp;
        }

        $config = $this->modules[$name];

        // 自定义模块类
        if (!empty($config['class'])) {
            $moduleClass    = $config['class'];
            $namespace      = self::spaceName($moduleClass);
            $config['path'] = Ulue::resolveAlias($config['path']);

            unset($config['class']);
        } else {
            $moduleClass    = ucfirst($name) . $this->suffix['module'];
            $namespace      = $name;
            $moduleClass    = $namespace .'\\'.ucfirst($moduleClass);
            $config['path'] = $this->basePath . '/' . $name;
        }

        if (!empty($config['path'])) {
            $config['path']  = Ulue::resolveAlias($config['path']);
            Ioc::$box->loader->setNs($namespace, $config['path'] );
        }

        $config['name']  = $name;
        $config['route'] = '/'.$name;

        /**
         * 激活顶级模块
         * @var $module \ulue\core\module\AbstractModule
         */
        $module = new $moduleClass( $config );

        // 还有子模块请求,继续激活子模块; 返回 最终请求到的模块实例
        if ($mRoute) {
            $module = $module->activeSubmodule($mRoute);

            // 最终请求到的模块路由
            $moduleRoute = $module->getRoute();
            $route = strpos(trim($moduleRoute,'/'),$temp)===0 ? substr($temp, strlen(trim($moduleRoute,'/')) ) : $temp;
            // d($moduleRoute, $temp, $route);
        }

        if (! $module instanceof AbstractModule) {
            throw new \DRuntimeException(sprintf('应用模块 [%s] 入口控制类 [%s] 必须继承自[\ulue\core\module\AbstractModule]!!', $name, $moduleClass));
        }

        $this->module = $module;

        unset($moduleClass, $config, $temp, $mRoute, $module);

        return trim($route,'/');
    }


    /**
     * __toString
     *
     * @return  string
     */
    public function __toString()
    {
        return $this->respond(true);
    }

    /**
     * @param $content
     * @return $this
     */
    public function setBody($content)
    {
        $this->getResponse()->setBody($content);

        return $this;
    }

    /**
     * @return array|null|string
     */
    public function getBody()
    {
        return $this->getResponse()->getBody();
    }

    /**
     * @return object|Response|InterfaceResponse
     */
    public function getResponse()
    {
        if (!$this->response) {
            $this->response = \Ioc::get('response');
        }

        return $this->response;
    }

    /**
     * @param InterfaceResponse $response
     * @return $this
     */
    public function setResponse(InterfaceResponse $response)
    {
        $this->response = $response;

        return $this;
    }


    public function quit($msg=null)
    {
        exit($msg);
    }
}